\section{Конвертирование температуры}

Еще один крайне популярный пример из книг по программированию для начинающих, это простейшая программа
для конвертирования температуры по Фаренгейту в температуру по Цельсию.

\[
	C=\frac{5 \cdot (F-32)}{9}
\]

Мы также добавим простейшую обработку ошибок:
1) мы должны проверять правильность ввода пользователем;
2) мы должны проверять результат, не ниже ли он $-273$ по Цельсию (что, как мы можем помнить из школьных
уроков физики, ниже абсолютного ноля).

\myindex{\CStandardLibrary!exit()}
Функция \TT{exit()} заканчивает программу тут же, без возврата в вызывающую функцию.

\subsection{Целочисленные значения}

\lstinputlisting[style=customc]{\CURPATH/i.c}

\subsubsection{\Optimizing MSVC 2012 x86}

\lstinputlisting[caption=\Optimizing MSVC 2012 x86,style=customasmx86]{\CURPATH/i_MSVC_2012_Ox_x86_RU.asm}

Что мы можем сказать об этом:

\begin{itemize}
\item Адрес функции \printf в начале загружается в регистр 
\ESI так что последующие вызовы
\printf происходят просто при помощи инструкции \TT{CALL ESI}.
Это очень популярная техника компиляторов, может присутствовать, если имеются несколько вызовов
одной и той же функции в одном месте, и/или имеется свободный регистр для этого.

\item Мы видим инструкцию \TT{ADD EAX, -32} в том месте где от значения должно отняться 32.
$EAX=EAX+(-32)$ эквивалентно $EAX=EAX-32$ и как-то компилятор решил использовать \TT{ADD} вместо \TT{SUB}.
Может быть оно того стоит, но сказать трудно.

\myindex{x86!\Instructions!LEA}
\item Инструкция \LEA используются там, где нужно умножить значение на 5: \\
	\TT{lea ecx, DWORD PTR [eax+eax*4]}.
Да, $i+i*4$ эквивалентно $i*5$ и \LEA работает быстрее чем \TT{IMUL}.
Кстати, пара инструкций \TT{SHL EAX, 2 / ADD EAX, EAX} может быть использована здесь
вместо \LEA --- некоторые компиляторы так и делают.

\item Деление через умножение (\myref{sec:divisionbymult}) также используется здесь.

\item Функция \main возвращает 0 хотя \TT{return 0} 
в конце функции отсутствует.
В стандарте C99 \InSqBrackets{\CNineNineStd 5.1.2.2.3} указано что \main 
будет возвращать 0 в случае отсутствия выражения 
\TT{return}.
Это правило работает только для функции \main.
И хотя, MSVC официально не поддерживает C99, может быть частично и поддерживает?

\end{itemize}

\subsubsection{\Optimizing MSVC 2012 x64}

Код почти такой же, хотя мы заметим инструкцию \TT{INT 3} после каждого вызова \TT{exit()}.

\begin{lstlisting}[style=customasmx86]
	xor	ecx, ecx
	call	QWORD PTR __imp_exit
	int	3
\end{lstlisting}

\TT{INT 3} это точка останова для отладчика.

Известно что функция \TT{exit()} из тех, что никогда не возвращают управление
\footnote{еще одна популярная из того же ряда это \TT{longjmp()}},
так что если управление все же возвращается, значит происходит что-то крайне странное, и пришло
время запускать отладчик.

\subsection{Числа с плавающей запятой}

\lstinputlisting[style=customc]{\CURPATH/f.c}

MSVC 2010 x86 использует инструкции \ac{FPU}\dots

\lstinputlisting[caption=\Optimizing MSVC 2010 x86,style=customasmx86]{\CURPATH/f_MSVC_2010_x86_Ox_RU.asm}

\dots но MSVC от года 2012 использует инструкции \ac{SIMD} вместо этого:

\lstinputlisting[caption=\Optimizing MSVC 2010 x86,style=customasmx86]{\CURPATH/f_MSVC_2012_x86_Ox_RU.asm}

Конечно, \ac{SIMD}-инструкции доступны и в x86-режиме, включая те что работают
с числами с плавающей запятой.
Их использовать в каком-то смысле проще, так что новый компилятор от Microsoft теперь применяет их.

Мы можем также заметить, что значение $-273$ загружается в регистр \XMM{0} слишком рано.
И это нормально, потому что компилятор может генерировать инструкции далеко не в том порядке, в котором
они появляются в исходном коде.
